package com.bidevalution.business.impl;

import com.bidevalution.business.context.ParamsType;
import com.bidevalution.business.context.SexType;
import com.bidevalution.business.context.SysIdentityCode;
import com.bidevalution.business.dto.BeSectionExpertInfoDTO;
import com.bidevalution.business.exception.ExpertException;
import com.bidevalution.business.service.BeExpertSpecialityService;
import com.bidevalution.business.service.BeSectionExpertInfoService;
import com.bidevalution.business.service.BeSectionInfoService;
import com.bidevalution.business.service.BeSysIdentityService;
import com.bidevalution.core.enums.ImportExpertSource;
import com.bidevalution.dao.entity.*;
import com.bidevalution.dao.mapper.*;
import com.bidevalution.model.ImportExpert;
import com.bidevalution.service.EntInfoService;
import com.bidevalution.support.context.Constants;
import com.bidevalution.support.util.StringUtil;
import com.qtp.auth.api.UserService;
import com.qtp.core.model.Response;
import com.qtp.core.util.*;
import com.qtp.user.models.SysUser;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by glodon on 2019-08-08.
 * 2020-03-25 胡一奇 BUG：ZTKP-3996 专家名字写错，删除专家，再次添加，输入身份证后提示的专家信息仍然是错的，并且无法修改。
 * 								   推送中标结果时的报表，专家多了一条数据。
 *
 */
@Log4j2
@Service
@Transactional(rollbackFor = Exception.class)
public class BeSectionExpertInfoServiceImpl implements BeSectionExpertInfoService {
	@Autowired(required = false)
	private BeSectionExpertInfoMapper beSectionExpertInfoMapper;

	@Autowired(required = false)
	private BeSectionExpertInfoDelMapper beSectionExpertInfoDelMapper;
	@Autowired(required = false)
	private BeExpertInfoMapper beExpertInfoMapper;
	@Autowired(required = false)
	private UserService userService;
	@Autowired(required = false)
	private BeSysParamsMapper beSysParamsMapper;
	@Autowired(required = false)
	private BeSectionInfoMapper beSectionInfoMapper;
	@Autowired(required = false)
	private BeSectionExpertProgressMapper beSectionExpertProgressMapper;
	@Autowired(required = false)
	private BeSectionExpertInfoService beSectionExpertInfoService;
	@Autowired(required = false)
	private EntInfoService entInfoService;
	@Autowired(required = false)
	private BeSysIdentityService beSysIdentityService;
	@Autowired(required = false)
	private BeExpertSpecialityService beExpertSpecialityService;
	@Autowired(required = false)
	private BeSectionInfoService beSectionInfoService;
	@Autowired
	private BeExpertVoteResultMapper beExpertVoteResultMapper;
	//2020-03-25 胡一奇 BUG：ZTKP-3996 专家名字写错，删除专家，再次添加，输入身份证后提示的专家信息仍然是错的，并且无法修改。
	//推送中标结果时的报表，专家多了一条数据。
	@Autowired(required = false)
	private BeExpertRegisterMapper beExpertRegisterMapper;

	private static final String IMPORT_EXPERT_FAIL_FORMAT = "%s，未获取成功，原因：%s。";


	@Value("${expert.generateMobile}")
	private String generateMobile;

	@Value("${expert.identityThirdCheck}")
	private String identityThirdCheck;
	/**
	 * 获取专家列表
	 * @param sectionId
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<BeSectionExpertInfo> getExpertListBySectionId(String sectionId,String voteType,String submitCode) throws Exception {
		return beSectionExpertInfoMapper.getExpertListBySectionId(sectionId,voteType,submitCode);
	}

	@Override
	public List<BeSectionExpertInfo> getExpertListBySectionId(String sectionId) {
		return beSectionExpertInfoMapper.getListBySectionId(sectionId);
	}

	/**
	 * 保存专家信息:判断用户系统是否存在
	 * @param beSectionExpertInfo
	 * @return
	 * @throws Exception
	 */
	@Override
	public Boolean saveExpertInfo(BeSectionExpertInfo beSectionExpertInfo,String password) throws Exception {
		//身份证号
		String cardNo = beSectionExpertInfo.getCardNo();
		String loginName = beSectionExpertInfo.getLoginName();
		String userName = beSectionExpertInfo.getName();
		//专家基本数据不存在时，进行新增操作
		if(beExpertInfoMapper.selectByCardNo(cardNo) == null) {
			BeExpertInfo beExpertInfo = new BeExpertInfo();
			PropertyUtils.copyProperties(beExpertInfo, beSectionExpertInfo);
			beExpertInfo.setSeqId(IdsUtil.uuid());
			if (beExpertInfoMapper.insert(beExpertInfo) != 1) {
				throw new Exception("专家基本信息保存失败");
			}
			/*Begin 2020-03-25 胡一奇 BUG：ZTKP-3996 专家名字写错，删除专家，再次添加，输入身份证后提示的专家信息仍然是错的，并且无法修改。
     推送中标结果时的报表，专家多了一条数据。*/
			//没有注册过
			Map<String, String> registeredExpert = beExpertRegisterMapper.expertRegistered(cardNo, userName);
			if(registeredExpert==null || registeredExpert.isEmpty()) {
				Map<String, Object> map = new HashMap<>();
				map.put("userName", userName);
				map.put("userLoginName", beSectionExpertInfo.getLoginName());
				map.put("userPassword", password);
				map.put("orgId", IdsUtil.uuid());
				map.put("orgName", beSectionExpertInfo.getWorkUnit());
				map.put("userSex", SexType.getCodeByName(beExpertInfo.getSex()));
				map.put("userMobile", beSectionExpertInfo.getPhone());
				map.put("roleGuids", "6150348b-8bab-4642-a641-9c39166ebe75");
				map.put("userLoginMethod", Constants.ONE);
				map.put("createUser", "评标专家2.0推送");
				//插入注册标记
				beExpertRegisterMapper.insertExpertRegister(cardNo, loginName, userName);
				Response registerResponse = userService.registeredUser(map);
				if (registerResponse != null) {
					if (registerResponse.isSuccess()) {
						return true;
					} else {
						log.error("专家账号推送失败，失败原因：" + registerResponse.getError());
						throw new Exception("专家账号推送失败，失败原因：" + registerResponse.getError());
					}
				} else {
					throw new Exception("专家账号推送失败");
				}
			} else {
				String loginNameBefore = registeredExpert.get("login_name");
				if(!loginNameBefore.equals(loginName)) {
					throw new Exception("专家已经注册过，请填写相同的登录名："+loginNameBefore);
				}
			}
			/*End 2020-03-25 胡一奇 BUG：ZTKP-3996 专家名字写错，删除专家，再次添加，输入身份证后提示的专家信息仍然是错的，并且无法修改。
     推送中标结果时的报表，专家多了一条数据。*/
		}
		return true;
	}

	@Override
	public Boolean saveSectionExpertInfo(BeSectionExpertInfo beSectionExpertInfo,String password) throws Exception {
		//身份证号
		String cardNo = beSectionExpertInfo.getCardNo();
		if (beSectionExpertInfoMapper.getSectionExpertInfo(beSectionExpertInfo.getSectionId(), cardNo) != null) {
			throw new Exception("专家信息已存在！");
		}
		for (BeSysParams beSysParams : beSysParamsMapper.selectForList(ParamsType.expertSource.name())) {
			if (beSectionExpertInfo.getExpertSource() != null && beSectionExpertInfo.getExpertSource().equals(beSysParams.getSypaValue())) {
				beSectionExpertInfo.setExpertSourceName(beSysParams.getSypaName());
			}
		}
		beSectionExpertInfo.setExpertCode(getExpertCode());
		if (beSectionExpertInfoMapper.insert(beSectionExpertInfo) != 1) {
			throw new Exception("专家信息保存失败");
		}
		return true;
	}

	/**
	 * 生成专家编号
	 * @return
	 */
	private String getExpertCode() {
		return DateUtil.getCurrentDateStr("MMddssSS").substring(0,8);
	}
	/**
	 * 删除专家信息
	 * @param seqIds
	 * @return
	 * @throws Exception
	 */
	@Override
	public Boolean deleteBeSectionExpertInfos(String seqIds) throws Exception {
		if (OConvertUtils.isNotEmpty(seqIds)) {
			String[] idArr = seqIds.split(",");
			for (String id : idArr) {
				if (beSectionExpertInfoMapper.deleteByPrimaryKey(id) != 1) {
					throw new Exception("删除失败");
				}
			}
		}
		return true;
	}

	@Override
	public List<BeSectionExpertInfo> getAllExpertListBySectionId(String sectionId) {
		List<BeSectionExpertInfo> infoList =  beSectionExpertInfoMapper.getListBySectionId(sectionId);
		infoList.addAll(beSectionExpertInfoDelMapper.getExpertDelListBySectionId(sectionId));
		return infoList;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void delBeSectionExpertInfos(String seqIds, String remark) {
		if (OConvertUtils.isNotEmpty(seqIds)) {
			String[] idArr = seqIds.split(",");
			for (String id : idArr) {
				//TODO 1.方欣接口校验时也有删除调用需注意
				BeSectionExpertInfo expert = beSectionExpertInfoMapper.selectByPrimaryKey(id);
				beSectionExpertInfoDelMapper.insertDelExpert(id, remark);
				beSectionExpertInfoMapper.deleteByPrimaryKey(id);
				/*Begin 2020-03-25 胡一奇 BUG：ZTKP-3996 专家名字写错，删除专家，再次添加，输入身份证后提示的专家信息仍然是错的，并且无法修改。
 								   推送中标结果时的报表，专家多了一条数据。*/
				if(expert!=null) {
					//删除推送表中的专家数据
					BeSectionInfo sectionInfo = beSectionInfoMapper.selectByPrimaryKey(expert.getSectionId());
					String sectionCode = sectionInfo.getSectionCode();
					String expertCode = expert.getExpertCode();
					beSectionExpertInfoMapper.deleteEvaluationRecord(sectionCode, expertCode);

					//判断之前的项目中是否有该专家，如果没有将be_expert_info表里的也删除
					Date createTime =  expert.getCreateTime();
					String date = DateUtil.dateToString(createTime, DateUtil.PT1);
					String cardNo = expert.getCardNo();
					long count = beSectionExpertInfoMapper.countBeforeExpert(cardNo, date);
					if(count==0) {
						BeExpertInfo expertInfo = beExpertInfoMapper.selectByCardNo(cardNo);
						if(expertInfo!=null) {
							String seqId = expertInfo.getSeqId();
							beExpertInfoMapper.deleteByPrimaryKey(seqId);
						}
					}
				}
				/*End 2020-03-25 胡一奇 BUG：ZTKP-3996 专家名字写错，删除专家，再次添加，输入身份证后提示的专家信息仍然是错的，并且无法修改。
 								   推送中标结果时的报表，专家多了一条数据。*/
			}
		}
	}

	@Override
	public void delBeSectionExpertBySectionId(String sectionId, String remark) {
		List<BeSectionExpertInfo> list = beSectionExpertInfoMapper.getList(sectionId, "0");
		if(list!=null) {
			String format = "%s,%s";
			String ids = "";
			for(BeSectionExpertInfo expertInfo:list) {
				ids = String.format(format, ids, expertInfo.getSeqId());
			}
			if(ids.length()>0) {
				ids = ids.substring(1, ids.length());
			}
			delBeSectionExpertInfos(ids, remark);
		}
	}

	/**
	 * 根据身份证号码查询专家基本库信息
	 * @param cardNo 身份证号码
	 * @return
	 * @throws Exception
	 */
	@Override
	public BeExpertInfo queryExpertInfoByCardNo(String cardNo) throws Exception {
		return beExpertInfoMapper.selectByCardNo(cardNo);
	}

	/**
	 * querySectionExpertInfoById
	 * @param seqId 根据主键查询
	 * @return
	 * @throws Exception
	 */
	@Override
	public BeSectionExpertInfo querySectionExpertInfoById(String seqId) throws Exception {
		return beSectionExpertInfoMapper.selectByPrimaryKey(seqId);
	}

	@Override
	public BeSectionExpertInfo selectByLoginName(String sectionId, String loginName) {
		// TODO Auto-generated method stub
		return beSectionExpertInfoMapper.selectByLoginName(sectionId, loginName);
	}

	@Override
	public Boolean updateAvoidReason(BeSectionExpertInfo beSectionExpertInfo) throws Exception {
		if (beSectionExpertInfoMapper.updateAvoidReason(beSectionExpertInfo) > 0) {
			BeSectionInfo beSectionInfo = new BeSectionInfo();
			beSectionInfo.setSeqId(beSectionExpertInfo.getSectionId());
			beSectionInfo.setReviewState(1);
			beSectionInfo.setUpdateTime(DateUtil.now());
			//更新标段评审状态为可以评审
			if (beSectionInfoMapper.updateByPrimaryKeySelective(beSectionInfo) < 1) {
				throw new Exception("更新标段评审状态失败！");
			}
			//有专家回避之后需要清空投票数据，重新推选
			beExpertVoteResultMapper.delBySectionId(beSectionExpertInfo.getSectionId(),Constants.ZERO.toString(),null);
			return true;
		}
		return false;
	}

	@Override
	public String isEnterReview(String sectionId, String loginName) throws Exception {
		String flag = Constants.TRUE;
		Map<String, Object> dataMap = beSectionExpertInfoMapper.queryByLoginName(sectionId, loginName);
		//专家不处于回避状态且评审状态已开始且环节数据已经同步成功
		if(beSectionExpertProgressMapper.selectBySectionIdAndExpertId(sectionId, dataMap.get("seqId").toString()).size() < 1){
			flag = "环节数据还未同步完成，请稍后。。。";
		}
		if(OConvertUtils.getInt(dataMap.get("reviewState")) < 2){
			flag = "招标代理还未点击评标开始，请稍后。。。";
		}
		if(OConvertUtils.getInt(dataMap.get("isAvoid")) == 1 ){
			flag = "您已回避评审此项目，不能进入评审！";
		}
		return flag;
	}

	@Override
	public List<String[]> findMd5ByLoginNames(String sectionId) throws Exception {
		List<String[]> list = new ArrayList<>();
		List<BeSectionExpertInfo> beSectionExpertInfos = beSectionExpertInfoMapper.getListBySectionId(sectionId);
		for (BeSectionExpertInfo beSectionExpertInfo: beSectionExpertInfos) {
			list.add(new String[]{Md5Util.getMD5(beSectionExpertInfo.getLoginName()).toUpperCase(), beSectionExpertInfo.getSeqId()});
//            list.add(new String[]{beSectionExpertInfo.getLoginName(), beSectionExpertInfo.getSeqId()});
		}
		return list;
	}

	@Override
	public Response importExperts(String sectionCode, String sectionId) throws Exception {
		log.info("LOG[]importExperts[]{},params={}", "专家设置-从接口获取专家信息", GsonUtil.toJsonWithGson(sectionCode)+";"+GsonUtil.toJsonWithGson(sectionId));
		try {
			//导入前删除所有旧专家
			beSectionExpertInfoService.delBeSectionExpertBySectionId(sectionId, "重新从接口获取专家");

			StringBuilder failReason = new StringBuilder();
			//从接口获取专家信息
			Response<List<ImportExpert>> rsp = entInfoService.getImportExperts(sectionCode);
			if(!rsp.isSuccess()) {
				throw new RuntimeException(rsp.getError());
			}
			List<ImportExpert> experts = rsp.getResult();
			for(ImportExpert expert:experts) {
				BeSectionExpertInfoDTO beSectionExpertInfoDTO = new BeSectionExpertInfoDTO();
				beSectionExpertInfoDTO.setSectionId(sectionId);
				beSectionExpertInfoDTO.setCardNo(expert.getExpertCode());
				beSectionExpertInfoDTO.setName(expert.getExpertName());
				beSectionExpertInfoDTO.setLoginName(expert.getExpertName());
				String value = beSysIdentityService.getValue(SysIdentityCode.MobileCode);
				beSectionExpertInfoDTO.setPhone(value);
				beSectionExpertInfoDTO.setExpertSource(ImportExpertSource.getSourceValue(expert.getSelectMode()));
				beSectionExpertInfoDTO.setSex("0");
				beSectionExpertInfoDTO.setPassword("123456");
				beSectionExpertInfoDTO.setFirstSpeciality(getFirstSpeciality(expert.getExpertSpeciality()));
				//保存、验证
				Response saveRsp = saveExpert(beSectionExpertInfoDTO);
				//组装失败专家的信息
				if(!saveRsp.isSuccess()) {
					if(StringUtils.isNotBlank(failReason)) {
						failReason.append("|");
					}
					failReason.append(String.format(IMPORT_EXPERT_FAIL_FORMAT, expert.getExpertName(), saveRsp.getError()));
				}
			}
			if(StringUtils.isNotBlank(failReason)) {
				throw new ExpertException(failReason.toString());
			} else {
				return Response.ok();
			}
		}catch (Exception e){
		    log.error("LOG[]importExperts[]{},error={},params={}","专家设置-从接口获取专家信息异常",GsonUtil.toJsonWithGson(e),GsonUtil.toJsonWithGson(sectionCode)+";"+GsonUtil.toJsonWithGson(sectionId));
		    throw e;
		}
	}

	private Response saveExpert(BeSectionExpertInfoDTO beSectionExpertInfoDTO) throws Exception {
		BeSectionExpertInfo beSectionExpertInfo = new BeSectionExpertInfo();
		beSectionExpertInfo.setSeqId(IdsUtil.uuid());
		beSectionExpertInfo.setSectionId(beSectionExpertInfoDTO.getSectionId());
		beSectionExpertInfo.setCardNo(beSectionExpertInfoDTO.getCardNo());
		beSectionExpertInfo.setName(beSectionExpertInfoDTO.getName());
		beSectionExpertInfo.setLoginName(beSectionExpertInfoDTO.getLoginName());
		beSectionExpertInfo.setWorkUnit(beSectionExpertInfoDTO.getWorkUnit());
		if ("1".equals(generateMobile)) {
			String value = beSysIdentityService.getValue(SysIdentityCode.MobileCode);
			beSectionExpertInfo.setPhone(StringUtil.getLenString(value, 11, "0"));
		} else {
			beSectionExpertInfo.setPhone(beSectionExpertInfoDTO.getPhone());
		}
		beSectionExpertInfo.setExpertType(beSectionExpertInfoDTO.getExpertType());
		beSectionExpertInfo.setAreaType(beSectionExpertInfoDTO.getAreaType());
		beSectionExpertInfo.setIsAvoid(Constants.ZERO);
		beSectionExpertInfo.setIsManager(Constants.ZERO);
		beSectionExpertInfo.setCreateTime(DateUtil.now());
		beSectionExpertInfo.setUpdateTime(DateUtil.now());
		beSectionExpertInfo.setExpertSource(beSectionExpertInfoDTO.getExpertSource());
		List<BeSysParams> beSysParamList = beSysParamsMapper.selectForList(ParamsType.expertSource.name());
		for (BeSysParams beSysParams : beSysParamList) {
			if (beSysParams.getSypaValue().equals(String.valueOf(beSectionExpertInfo.getExpertSource()))) {
				beSectionExpertInfo.setExpertSourceName(beSysParams.getSypaName());
				break;
			}
		}
		beSectionExpertInfo.setFirstSpeciality(beSectionExpertInfoDTO.getFirstSpeciality());
		beSectionExpertInfo.setSecondSpeciality(beSectionExpertInfoDTO.getSecondSpeciality());
		beSectionExpertInfo.setThirdSpeciality(beSectionExpertInfoDTO.getThirdSpeciality());
		beSectionExpertInfo.setFourSpeciality(beSectionExpertInfoDTO.getFourSpeciality());
		beSectionExpertInfo.setSex(beSectionExpertInfoDTO.getSex());
		beSectionExpertInfo.setIsIdentity("1");
		//五库验证之前，需要保存标段专家信息（最初设计如此）
		if (!beSectionExpertInfoService.saveSectionExpertInfo(beSectionExpertInfo, beSectionExpertInfoDTO.getPassword())) {
			return Response.fail("保存标段专家信息失败");
		}
		if ("1".equals(identityThirdCheck)) {
			log.info(beSectionExpertInfoDTO + "**************IdentityThirdCheck");
			if (beSectionExpertInfoDTO.getExpertSource() == null) {
				return Response.fail("专家来源不能为空");
			}
			if (StringUtils.isBlank(beSectionExpertInfoDTO.getCardNo())) {
				return Response.fail("专家身份证号不能为空");
			}
			if (StringUtils.isBlank(beSectionExpertInfoDTO.getName())) {
				return Response.fail("专家姓名不能为空");
			}
			//建委五库-方欣
			BeSectionInfo beSectionInfo = beSectionInfoService.getBeSectionInfoById(beSectionExpertInfoDTO.getSectionId());
			Response<String> response = entInfoService.getExportInfo(beSectionExpertInfoDTO.getCardNo(), beSectionExpertInfoDTO.getName(), beSectionInfo.getSectionCode());
			if (!response.isSuccess()) {
				beSectionExpertInfoService.deleteBeSectionExpertInfos(beSectionExpertInfo.getSeqId());
				return Response.fail(response.getError());
			}
		}
		if (!beSectionExpertInfoService.saveExpertInfo(beSectionExpertInfo, beSectionExpertInfoDTO.getPassword())) {
			return Response.fail("保存失败");
		}
		return Response.ok("保存成功");
	}

	private String getFirstSpeciality(String expertSpeciality) {
		String spec = "";
		if(StringUtils.isNotBlank(expertSpeciality)) {
			String firstSpeciality = expertSpeciality.split(" &gt; ")[0];
			BeExpertSpeciality speciality = beExpertSpecialityService.getSpecialityByName(firstSpeciality);
			if(speciality != null) {
				spec = speciality.getId().toString();
			}
		}
		return spec;
	}

	@Override
	public List<BeSectionExpertInfo> getAllListBySectionId(String sectionId) throws Exception {

		return beSectionExpertInfoMapper.getListBySectionId(sectionId);
	}

	@Override
	public List<BeSectionExpertInfo> getListBySectionId(String sectionId, String isAvoid) throws Exception {

		return beSectionExpertInfoMapper.getList(sectionId, isAvoid);
	}
}
